﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;
using Agr.CQRS;
using Agr.Questionnaire.Core.ViewModel.Qnnaire;
using log4net;
using Spark;
using Spark.Web.Mvc;
using Agr.CQRS.ViewModel;

namespace Agr.Questionnaire.Frontend
{
    public class MvcApplication : System.Web.HttpApplication
    {
        static ILog Logger = LogManager.GetLogger(typeof(MvcApplication).Name);

        public MvcApplication()
        {
            log4net.Config.XmlConfigurator.Configure();

            this.BeginRequest += new EventHandler(MvcApplication_BeginRequest);
            this.EndRequest += new EventHandler(MvcApplication_EndRequest);
        }

        protected void Application_Start()
        {
            Logger.Warn("Application start");

            RegisterRoutes(RouteTable.Routes);
            RegisterViewEngine(ViewEngines.Engines);

            bootstrapQCRS();
        }

        protected void Application_End()
        {
            Logger.Warn("Application shutdown");

            shutdownQCRS();
        }

        protected void Application_Error()
        {
            Logger.Error("Unhandled exception", Server.GetLastError());
        }

        #region ViewModel consumer setup
        public static BootstrappedViewModel ViewModel;

        void MvcApplication_BeginRequest(object sender, EventArgs e)
        {
            disposeQueryFactory();
            Context.Items["ViewModelQueryFactory"] = ViewModel.CreateViewModelQueryFactory();
        }
        void MvcApplication_EndRequest(object sender, EventArgs e)
        {
            disposeQueryFactory();
        }
        private void disposeQueryFactory()
        {
            var qf = Context.Items["ViewModelQueryFactory"] as ViewModelQueryFactory;
            if (qf == null)
                return;

            qf.Dispose();
            Context.Items.Remove("ViewModelQueryFactory");
        }
        #endregion

        #region QCRS parts bootstrapper

        private Bootstrapper bootstrapper;
        public static BootstrappedDomainModel DomainModel;
        public static BootstrappedViewModelUpdater ViewModelUpdater;

        private void bootstrapQCRS()
        {
            //generic bootstrapper
            bootstrapper = new Bootstrapper("Server=.;initial catalog=Qnnaire;Integrated Security=SSPI", typeof(QuestionnaireInList).Assembly);

            //bootstrapper.CreateSchema();
            
            //bootstrapper for the domain model (to send commands to)
            DomainModel = bootstrapper.BootstrapDomainModel();

            //bootstrapper for services that keeps the viewmodel in sync
            ViewModelUpdater = bootstrapper.BootstrapViewModelUpdater(
                typeof(QuestionnaireInListUpdater),
                typeof(QuestionnaireDetailUpdater)
             );

            //bootstrapper for viewmodel queries
            ViewModel = bootstrapper.BootstrapViewModelRepository();
        }

        private void shutdownQCRS()
        {
            DomainModel = null;
            ViewModelUpdater.Stop();
            ViewModelUpdater = null;
            ViewModel = null;

            bootstrapper.Dispose();
            bootstrapper = null;
        }
        #endregion

        #region MVC routes and spark view engine setup
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            //use all possible namespaces in this webapp for controller locations
            var namespaces = (
                from t in typeof(MvcApplication).Assembly.GetExportedTypes()
                select t.Namespace
              ).Distinct().ToArray();

            routes.MapRoute("Default", "{controller}/{action}/{id}/{version}",
                new { controller = "QnnaireList", action = "Index", id = "", version = 0 },
                namespaces
            );

        }

        public static void RegisterViewEngine(ViewEngineCollection engines)
        {
            var settings = new SparkSettings();

            // comment this if you want to use Html helpers with the ${} syntax:
            // otherwise you would need to use the <%= %> syntax with anything that outputs html code
            settings.SetAutomaticEncoding(true);

            settings
                .AddNamespace("System")
                .AddNamespace("System.Collections.Generic")
                .AddNamespace("System.Linq")
                .AddNamespace("System.Web.Mvc")
                .AddNamespace("System.Web.Mvc.Html")
                .AddNamespace("Microsoft.Web.Mvc");
            // Add here more namespaces to your model classes
            // or whatever classes you need to use in the views

            var prms = new Dictionary<string, string>();
            prms.Add("virtualBaseDir", "~/Mvc");
            settings.AddViewFolder(Spark.FileSystem.ViewFolderType.VirtualPathProvider, prms);

            settings
                .AddAssembly("Microsoft.Web.Mvc")
                .AddAssembly("Spark.Web.Mvc")
                .AddAssembly("System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")
                .AddAssembly("System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");

            engines.Add(new SparkViewFactory(settings));
        }
        #endregion
    }
}